package com.bruce.hmily_provider_usercoupon.service.impl;

import com.bruce.hmily_entity.LocalCancelLog;
import com.bruce.hmily_entity.LocalConfirmLog;
import com.bruce.hmily_entity.LocalTryLog;
import com.bruce.hmily_entity.UserCoupon;
import com.bruce.hmily_provider_usercoupon.service.UserCouponService;
import com.bruce.hmily_repository.LocalCancelRepository;
import com.bruce.hmily_repository.LocalConfirmRepository;
import com.bruce.hmily_repository.LocalTryRepository;
import com.bruce.hmily_repository.UserCouponRepository;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.Hmily;
import org.dromara.hmily.core.concurrent.threadlocal.HmilyTransactionContextLocal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.HashMap;

/**
 * 类注释
 *
 * @author Bruce
 * @date 2021/3/22 9:39 AM
 */
@Service
@Slf4j
public class UserCouponServiceImpl implements UserCouponService {

    @Autowired
    private UserCouponRepository userCouponRepository;

    @Autowired
    private LocalTryRepository tryRepository;
    @Autowired
    private LocalConfirmRepository confirmRepository;
    @Autowired
    private LocalCancelRepository cancelRepository;

    @Hmily(confirmMethod = "saveConfirm", cancelMethod = "saveCancel")
    @Override
    public UserCoupon save(UserCoupon userCoupon) {
        log.info("------->UserCoupon save begin");

        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("------->UserCoupon save transId:" + transId);

        log.info("------->UserCoupon save end");
        return userCoupon;
    }

    /**
     * 主事务confirm方法执行完成后，此处子事务的confirm方法才开始执行
     * @param userCoupon
     * @return
     */
    @Transactional
    public UserCoupon saveConfirm(UserCoupon userCoupon) {
        log.info("------->UserCoupon saveConfirm begin");

        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("------->UserCoupon saveConfirm transId:" + transId);

        //1.幂等校验
        if (confirmRepository.existsById(transId)) {
            log.info(String.format("------->UserCoupon saveConfirm 幂等校验，此transId:%s已经执行，无须重复执行", transId));
            return null;
        }

        //2.执行操作，若不加异常处理，则执行失败后会自动重试，也可以捕获异常后，用其他服务重试
        try {
            userCoupon = userCouponRepository.save(userCoupon);
            //TODO 需要执行的操作
        }
        catch (Exception ex){
            //如果操作失败，则需要通知系统，此数据必须成功
            //TODO 将需要操作的数据插入消息队列，由另外服务时时处理此类型的数据
            log.error("------->UserCoupon saveConfirm error，此UserCouponId数据必须成功");
        }

        //模拟异常
        long tmpVal = System.currentTimeMillis();
        if (tmpVal % 2 == 0) {
            log.info("------->UserCoupon saveConfirm 模拟异常，触发重试机制");
            throw new RuntimeException("模拟异常");
        }

        //3.幂等插入
        LocalConfirmLog confirmLog = new LocalConfirmLog();
        confirmLog.setTx_no(transId);
        confirmLog.setCreate_time(Calendar.getInstance().getTime());
        confirmRepository.save(confirmLog);

        log.info("------->UserCoupon saveConfirm end");

        return userCoupon;
    }

    public UserCoupon saveCancel(UserCoupon userCoupon) {
        log.info("------->UserCoupon saveCancel begin");

        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("------->UserCoupon saveCancel transId:" + transId);

        log.info("------->UserCoupon saveCancel end");
        return userCoupon;
    }

    @Override
    public UserCoupon findByUserCouponId(long id) {
        return userCouponRepository.findByUserCouponId(id);
    }
}
